/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						       dialog_options_base.cpp

	$Header: /game/dialog_options_base.cpp $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "dialog_options_base.h"

#include "adaptor_handler.h"
#include "bitmap_layer_window.h"
#include "bound_handler.h"
#include "button_cache.h"
#include "external_string.h"
#include "format_string.h"
#include "interface_help.h"
#include "platform.h"
#include "music.h"
#include "options.h"
#include "scrollbar.h"
#include "sound.h"
#include "standard_fonts.h"
#include "text_window.h"


extern t_button_cache g_large_button;
extern t_button_cache g_ok_button;
extern t_button_cache g_cancel_button;

// ---------------------------------------------------------------------
// options dialog.  Currently only show screen mode / resolution.
// ---------------------------------------------------------------------
t_dialog_options_base::t_dialog_options_base( t_window* parent, t_bitmap_group_ptr bitmaps )
                    : t_window( k_completely_transparent, parent )
{
	t_help_block const&		options_help = get_help_block( "options_menu" );
	t_bitmap_layer const*	layer;
	m_bitmaps = bitmaps;

	layer = m_bitmaps->find( "background" );
	m_background = new t_bitmap_layer_window( layer, t_screen_point(0,0), this );

	t_screen_rect window_size = m_background->get_client_rect();
	t_screen_rect rect;

	// add "OK" button
	t_button* button;

	rect = m_bitmaps->find( "ok_button" )->get_rect();
	button = new t_button( g_ok_button.get(), rect.top_left(), m_background );
	button->set_click_handler( bound_handler( *this, &t_dialog_options_base::ok_clicked ));
	set_help( button, options_help, "ok" );

	// add "cancel" button
	rect = m_bitmaps->find( "cancel_button" )->get_rect();
	button = new t_button( g_cancel_button.get(), rect.top_left(), m_background );
	button->set_click_handler( bound_handler( *this, &t_dialog_options_base::cancel ));
	set_help( button, options_help, "cancel" );

	window_size += t_screen_point( (parent->get_width() - window_size.width()) / 2, 
		                           (parent->get_height() - window_size.height()) / 2 );
	init( window_size );

	create_scrollbars();
}

// ---------------------------------------------------------------------
// create a text item
// ---------------------------------------------------------------------
void t_dialog_options_base::create_text( char const* label, std::string text )
{
	t_text_window*  text_window;
	t_screen_rect	rect;

	rect = m_bitmaps->find( label )->get_rect();
	text_window = new t_text_window( get_font( rect.height() ), rect, m_background, text,
		                             t_pixel_24(0,0,0));
	text_window->set_drop_shadow( true, t_pixel_24(200,200,200));
	text_window->set_center_horizontal();
}

t_text_window* t_dialog_options_base::create_text_with_value( char const* label, std::string text, int value )
{
	t_text_window*  text_window;
	t_screen_rect	rect;

	rect = m_bitmaps->find( label )->get_rect();
	text_window = new t_text_window( get_font( rect.height() ), rect, m_background, text,
		                             t_pixel_24(0,0,0));
	text_window->set_drop_shadow( true, t_pixel_24(200,200,200));
	text_window->set_justification( k_justify_left );
	
    rect = m_bitmaps->find( label )->get_rect();
	text_window = new t_text_window( get_font( rect.height() ), rect, m_background, format_string("%d", convert_speed_from_linear( value )),
		                             t_pixel_24(0,0,0));
	text_window->set_drop_shadow( true, t_pixel_24(200,200,200));
	text_window->set_justification( k_justify_right );

    return text_window;
}

void t_dialog_options_base::set_text_value( t_text_window* text_window, int value )
{
	text_window->set_text( format_string("%d", value ) );
}

// ---------------------------------------------------------------------
// convert to/from animation speed scales
// ---------------------------------------------------------------------
double const k_log_2 = 0.693147180559945309417232121458177;

int t_dialog_options_base::convert_speed_from_linear( int value )
{
	double result = log( value * 0.01 ) * 2.0 / k_log_2;

	if (result > 0.0)
		return result + 0.5;
	return result - 0.5;
}

int t_dialog_options_base::convert_speed_to_linear( int value )
{
	return exp( value * k_log_2 * 0.5 ) * 100.0 + 0.5; 
}

// ---------------------------------------------------------------------
// create scrollbars
// ---------------------------------------------------------------------
static t_external_string const k_text_sound( "Sound.dialog" );
static t_external_string const k_text_music( "Music.dialog" );
static t_external_string const k_text_animation_speed( "Animation_Speed.dialog" );
static t_external_string const k_text_combat_speed( "Combat.dialog" );

void t_dialog_options_base::create_scrollbars()
{
	t_scrollbar*        scrollbar;
	t_screen_rect       rect;
	t_scrollbar_handler handler;
	t_help_block const&   options_help = get_help_block( "options_menu" );

	m_old_sound_volume = get_sound_volume();
	rect = m_bitmaps->find( "sound_volume" )->get_rect();
	scrollbar = new t_scrollbar( rect.top_left(), rect.width(), m_background, 0, 100, false );
	scrollbar->set_position( get_linear_volume( m_old_sound_volume ) );
	handler = bound_handler( *this, &t_dialog_options_base::sound_change );
	scrollbar->set_handler( handler );
	set_help( scrollbar, options_help, "effects_volume" );

	//create_text( "sound_text", k_text_sound );
	m_sound_text_window = create_text_with_value( "sound_text", k_text_sound,
								 m_old_sound_volume );
	set_text_value( m_sound_text_window, get_linear_volume(m_old_sound_volume) );

	m_old_music_volume = get_music_volume();
	rect = m_bitmaps->find( "music_volume" )->get_rect();
	scrollbar = new t_scrollbar( rect.top_left(), rect.width(), m_background, 0, 100, false );
	scrollbar->set_position( get_linear_volume( m_old_music_volume ) );
	handler = bound_handler( *this, &t_dialog_options_base::music_change );
	scrollbar->set_handler( handler );
	set_help( scrollbar, options_help, "music_volume" );

	//create_text( "music_text", k_text_music );
	m_music_text_window = create_text_with_value( "music_text", k_text_music,
								 m_old_music_volume );
	set_text_value( m_music_text_window, get_linear_volume(m_old_music_volume) );

	// animation speeds
	//create_text( "army_speed_text", k_text_animation_speed );
	int linear_speed;
	
	m_combat_speed = get_combat_animation_speed();
	m_combat_speed_text_window = create_text_with_value( "combat_speed_text", k_text_combat_speed,
								 m_combat_speed );
	rect = m_bitmaps->find( "combat_animation_speed" )->get_rect();
	scrollbar = new t_scrollbar( rect.top_left(), rect.width(), m_background, -2, 6, false );
	linear_speed = convert_speed_from_linear( m_combat_speed );
	scrollbar->set_position( linear_speed );
	handler = bound_handler( *this, &t_dialog_options_base::combat_speed_change );
	scrollbar->set_handler( handler );
	set_help( scrollbar, options_help, "combat_speed" );
}

// ---------------------------------------------------------------------
// options dialog
// respond to sound volume change
// ---------------------------------------------------------------------
void t_dialog_options_base::sound_change( t_scrollbar*, int value )
{
	set_sound_volume( get_millibel_volume( value ) );
	set_text_value( m_sound_text_window, value );
}

// ---------------------------------------------------------------------
// options dialog
// respond to sound volume change
// ---------------------------------------------------------------------
void t_dialog_options_base::music_change( t_scrollbar*, int value )
{
	set_music_volume( get_millibel_volume( value ));
	set_text_value( m_music_text_window, value );
}

// ---------------------------------------------------------------------
// options dialog
// respond to speed change
// ---------------------------------------------------------------------
void t_dialog_options_base::combat_speed_change( t_scrollbar*, int value )
{
	m_combat_speed = convert_speed_to_linear( value );
    set_text_value( m_combat_speed_text_window, value );
}

// ---------------------------------------------------------------------
// options dialog
// cancel dialog
// ---------------------------------------------------------------------
void t_dialog_options_base::cancel( t_button* )
{
	m_return_value = false;
	set_sound_volume( m_old_sound_volume );
	set_music_volume( m_old_music_volume );
	close();
}

void t_dialog_options_base::ok_clicked( t_button* )
{
	m_return_value = true;
	set_combat_animation_speed( m_combat_speed );
	close();
}

extern t_button_cache g_checkbox;

t_toggle_button* t_dialog_options_base::add_checkbox( std::string const&	name,    
													  t_button_handler		handler,
													  bool					pressed, 
													  std::string const&	text,
													  t_help_block const *  help)
{
	t_screen_rect    rect;
	t_toggle_button* checkbox;
	t_text_window*	 text_window;

	rect = m_bitmaps->find( name + "_checkbox" )->get_rect();
	checkbox = new t_toggle_button( g_checkbox.get(), rect.top_left(), m_background );
	checkbox->set_pressed( pressed );
	checkbox->set_click_handler( handler );
	rect = m_bitmaps->find( name + "_text" )->get_rect();
	text_window = new t_text_window( get_font( rect.height() ), rect, m_background,
									 text, t_pixel_24(0,0,0) );
	text_window->set_drop_shadow( true, t_pixel_24(200,200,200) );
	//text_window->set_center_horizontal();

	if ( help )
	{
		set_help( checkbox, *help, name );
		set_help( text_window, *help, name );
	}

	return checkbox;
}
